package pt.inescid.components.policyengine.heimdall.core;

import java.util.Vector;

import pt.inescid.components.policyengine.heimdall.pdp.base.ModelInstance;

public class QueueManager extends Thread {

	public static final int RECEPTION_QUEUE = 0;
	public static final int EVENTS_IN_PROCESS_QUEUE = 3;
	public static final int EVENTS_IN_LEASE_QUEUE = 4;
	public static final int PROCESSED_EVENTS_QUEUE = 6;
	
	
	
	/* ===========================================================
	==============================================================
	==============================================================
	initQueues
	==============================================================
	==============================================================
	=========================================================== */
	public static void initQueues() { 
//		eventsToStore = new Vector();
//		eventsToProcess = new Vector();

    	HeimdallServer server = HeimdallServer.getInstance();

    	server.receptionQueue = new Vector();
    	server.eventsInProcess = new Vector();
    	server.eventsInLease = new Vector();
    	server.eventsInReevaluation = new Vector();
    	server.eventsInObligation = new Vector();
    	server.processedEvents = new Vector();
	}
	
	
	/* ===========================================================
	==============================================================
	==============================================================
	addToQueue
	==============================================================
	==============================================================
	=========================================================== */
	public static void addToQueue(Object obj, int queue) {
		
		Vector queueObj = null;
		
    	HeimdallServer server = HeimdallServer.getInstance();

    	switch (queue) {
		case RECEPTION_QUEUE:
			queueObj = server.receptionQueue;
			break;
		case EVENTS_IN_PROCESS_QUEUE:
			queueObj = server.eventsInProcess;
			break;
		case EVENTS_IN_LEASE_QUEUE:
			queueObj = server.eventsInLease;
			break;
		case PROCESSED_EVENTS_QUEUE:
			queueObj = server.processedEvents;
			break;
		default:
			return;
		}
		
		synchronized (queueObj) {
			if (queue != EVENTS_IN_LEASE_QUEUE) {
				queueObj.add(obj);
			}
			else {
				ModelInstance currentModel = null;
				boolean found = false;
				
				for (int i = 0; i < server.eventsInLease.size(); i++) {
					currentModel = (ModelInstance) 
							server.eventsInLease.elementAt(i);
					
					if (currentModel.getLeaseTimestamp() < 
						((ModelInstance) obj).getLeaseTimestamp()) {
						
						server.eventsInLease.insertElementAt((ModelInstance)obj, i);
						i = server.eventsInLease.size();
						found = true;
					}
				}
				
				if (!found) {
					server.eventsInLease.add((ModelInstance)obj);
				}
			}
		}
	} // addToQueue
	
	
		
	/* ===========================================================
	==============================================================
	=============                    =============================
	=============      getNextFromQueue       =============================
	=============                    =============================
	==============================================================
	=========================================================== */
	public static Object getNextFromQueue(int queue, boolean remove) {

		Vector queueObj = null;
		Object objToReturn = null;
		
    	HeimdallServer server = HeimdallServer.getInstance();

		switch (queue) {
		case RECEPTION_QUEUE:
			queueObj = server.receptionQueue;
			break;
		case EVENTS_IN_PROCESS_QUEUE:
			queueObj = server.eventsInProcess;
			break;
		case EVENTS_IN_LEASE_QUEUE:
			queueObj = server.eventsInLease;
			break;
		case PROCESSED_EVENTS_QUEUE:
			queueObj = server.processedEvents;
			break;
		default:
			return (null);
		}

		synchronized (queueObj) {
			if (queueObj.size() > 0) {
				
				// in the reception queue, new infos have priority,
				// in order to speed up policy evaluation
				if (queue == RECEPTION_QUEUE) {
					boolean found = false;
					ReceptionQueueNode currentNode = null;
					
					for (int i = 0; i < queueObj.size(); i++) {
						currentNode = (ReceptionQueueNode) queueObj.elementAt(i);
						if (currentNode.getType() == 
							ReceptionQueueNode.REQUEST_PROCESS_NEW_INFO) {
							
							found = true;
							i = queueObj.size();
						}
					}
					
					if (found) {
						objToReturn = currentNode;
					}
				}
				
				if (objToReturn == null) {
					objToReturn = queueObj.elementAt(0);
				}

				if (remove) {
					queueObj.removeElement(objToReturn);
				}
			}
		}
		
		return (objToReturn);
	} // getNextFromQueue
} // QueueManager
